#include "AbstractChannel.h"
#include "../eventloop.h"
#include "../event_manager.h"
#include "tinyrpc/base/logger/logger.h"
namespace TinyRPC{

AbstractChannel::AbstractChannel(int fd)
: m_fd(fd){
    
    m_event = std::make_shared<Event>(fd, this);
    // 在EventManager里面注册Channel对应的Event
    EventManager::GetInstance().addEventPtr(m_event);
    m_fdStatus = FdStatus::OPEN;
    // m_event->enableReading();
    // m_event->setReadTask(Task(std::bind(&WakeupChannel::read, this), false));
}

void AbstractChannel::close(){
    if(m_fdStatus != CLOSED){
        m_fdStatus = CLOSED;
        EventManager::GetInstance().delEventPtr(m_fd);
        deleteEvent(EventLoop::CurrentEventLoop(), ReadEvent | WriteEvent);
        ::close(m_fd);
    }
}

AbstractChannel::~AbstractChannel(){
    close();
}

void AbstractChannel::modifyEvent(EventLoop * ownerLoop){
    if(m_event->getStatus() == EventStatus::ADDED && ownerLoop){
        ownerLoop->modifyEvent(m_event);
        LOG_INFO<<"modify event in epoll, fd:"<<m_event->getFd()<<" new event: "<<m_event->getEventOP();
    }
}

// 向epoll添加event
void AbstractChannel::addEvent(EventLoop * ownerLoop){
    if((m_event->getStatus() == EventStatus::INTIED || m_event->getStatus()== EventStatus::DELETED ) && ownerLoop){
        ownerLoop->addEvent(m_event);
        LOG_INFO<<"add event in epoll, fd:"<<m_event->getFd()<<" new event: "<<m_event->getEventOP();
        m_event->setStatus(EventStatus::ADDED);
    }
}


// 
void AbstractChannel::deleteEvent(EventLoop * ownerLoop, int interestOp){
    int oldEvent = m_event->getEventOP();
    if(interestOp & ReadEvent && oldEvent&ReadEvent ){
        m_event->disableReading();
    }
    if(interestOp & WriteEvent && oldEvent&WriteEvent ){
        m_event->disableWriting();
    }

    //并未做任何改变
    if(m_event->getEventOP() == oldEvent){
        return;
    }else if(m_event->getStatus() == EventStatus::ADDED){
        if(m_event->getEventOP() == NoneEvent){
            ownerLoop->deleteEvent(m_event);
            m_event->setStatus(EventStatus::DELETED);
        }else{
            modifyEvent(ownerLoop);
        }
    }
}



// 既可以是 添加 修改 
void AbstractChannel::updateEvent(int interestOp, const Task& task, EventLoop * ownerLoop){

    // 已经添加过了 并且这次关注的事情和之前相同， 则不需要修改了epoll 红黑树了
    // 只需要重新设置一下readTask 
    if((m_event->getStatus() == EventStatus::ADDED)&&(m_event->getEventOP() & interestOp)){
        if(interestOp == ReadEvent) {
            m_event->setReadTask(task);
        }else if(interestOp == WriteEvent){
            m_event->setWriteTask(task);
        }
        return;
    }

    int oldEvent = m_event->getEventOP();
    //m_event->enableNone();
    if(interestOp == ReadEvent) {
        m_event->enableReading();
        m_event->setReadTask(task);
    }else if(interestOp == WriteEvent){
        m_event->enableWriting();
        m_event->setWriteTask(task);
    }

    // 还没有被添加 或者删除时 , 需要添加
    if(m_event->getStatus() == EventStatus::INTIED || m_event->getStatus()== EventStatus::DELETED && m_event->getEventOP() != oldEvent){
        addEvent(ownerLoop);
    }
    
    else if(m_event->getStatus() == EventStatus::ADDED && m_event->getEventOP() != oldEvent){
        modifyEvent(ownerLoop);
    }
    
}



bool AbstractChannel::setBlock(bool isblock)
{
	int re = 0;
//通过宏区分windows和linux，如果是windows64位程序判断 _WIN64宏

	//先取到现有描述符属性，保证本次更改不变动原有属性
	int flags = fcntl(m_fd, F_GETFL, 0);
	if (flags < 0) {
		return false;
	}
	if(isblock)
	{
		flags = flags & ~O_NONBLOCK;
	}
	else
	{
		flags = flags | O_NONBLOCK;
	}
	re = fcntl(m_fd, F_SETFL, flags);

	if (re != 0) return false;
	return true;
}

}
